package com.vhall.component.entity.logger;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.vhall.component.plugin.common.enums.OperateTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * 操作日志表
 *
 * @author mingming.shi
 */
@Data
@TableName("system_operate_log")
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "OperateLogEntity对象", description = "系统操作日志表")
public class OperateLogEntity {

    /**
     * {@link #javaMethodArgs} 的最大长度
     */
    public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 7000;

    /**
     * {@link #resultData} 的最大长度
     */
    public static final Integer RESULT_MAX_LENGTH = 4000;

    /**
     * 日志主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 链路追踪编号
     * <p>
     * 一般来说，通过链路追踪编号，可以将访问日志，错误日志，链路追踪日志，logger 打印日志等，结合在一起，从而进行排错。
     */
    @ApiModelProperty(value = "链路追踪编号")
    @JsonProperty("trace_id")
    @TableField("trace_id")
    private String traceId;

    /**
     * 用户昵称
     */
    @ApiModelProperty(value = "用户昵称")
    @JsonProperty("user_nickname")
    @TableField("user_nickname")
    private String userNickname;

    /**
     * 用户编号
     * <p>
     * 关联 MemberUserDO 的 id 属性，或者 AdminUserDO 的 id 属性
     */
    @ApiModelProperty(value = "用户编号")
    @JsonProperty("user_id")
    @TableField("user_id")
    private Long userId;

    /**
     * 用户类型
     * <p>
     * 关联 {@link  UserTypeEnum}
     */
    @ApiModelProperty(value = "用户类型")
    @JsonProperty("user_type")
    @TableField("user_type")
    private Integer userType;

    /**
     * 操作模块
     */
    @ApiModelProperty(value = "操作模块")
    @JsonProperty("module")
    @TableField("module")
    private String module;

    /**
     * 操作名
     */
    @ApiModelProperty(value = "操作名")
    @JsonProperty("name")
    @TableField("name")
    private String name;

    /**
     * 操作分类
     * <p>
     * 枚举 {@link OperateTypeEnum}
     */
    @ApiModelProperty(value = "操作分类")
    @JsonProperty("type")
    @TableField("type")
    private Integer type;
    /**
     * 操作内容，记录整个操作的明细
     * 例如说，修改编号为 1 的用户信息，将性别从男改成女，将姓名从芋道改成源码。
     */
    @ApiModelProperty(value = "操作内容")
    @JsonProperty("content")
    @TableField("content")
    private String content;

    /**
     * 拓展字段，有些复杂的业务，需要记录一些字段
     * 例如说，记录订单编号，则可以添加 key 为 "orderId"，value 为订单编号
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    @ApiModelProperty(value = "拓展字段")
    @JsonProperty("exts")
    private Map<String, Object> exts;

    /**
     * 请求方法名
     */
    @ApiModelProperty(value = "请求方法名")
    @JsonProperty("request_method")
    @TableField("request_method")
    private String requestMethod;

    /**
     * 请求地址
     */
    @ApiModelProperty(value = "请求地址")
    @JsonProperty("request_url")
    @TableField("request_url")
    private String requestUrl;

    /**
     * 用户 IP
     */
    @ApiModelProperty(value = "用户 IP")
    @JsonProperty("user_ip")
    @TableField("user_ip")
    private String userIp;

    /**
     * 浏览器 UA
     */
    @ApiModelProperty(value = "浏览器 UA")
    @JsonProperty("user_agent")
    @TableField("user_agent")
    private String userAgent;

    /**
     * Java 方法名
     */
    @ApiModelProperty(value = "Java 方法名")
    @JsonProperty("java_method")
    @TableField("java_method")
    private String javaMethod;

    /**
     * Java 方法的参数
     * <p>
     * 实际格式为 Map<String, Object>
     * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是，数据库存储有长度限制，会进行裁剪，会导致 JSON 反序列化失败
     * 其中，key 为参数名，value 为参数值
     */
    @ApiModelProperty(value = "Java 方法的参数")
    @JsonProperty("java_method_args")
    @TableField("java_method_args")
    private String javaMethodArgs;

    /**
     * 开始时间
     */
    @ApiModelProperty(value = "账户编号")
    @JsonProperty("start_time")
    @TableField("start_time")
    private LocalDateTime startTime;

    /**
     * 执行时长，单位：毫秒
     */
    @ApiModelProperty(value = "执行时长，单位：毫秒")
    @JsonProperty("duration")
    @TableField("duration")
    private Integer duration;

    /**
     * 结果码
     * <p>
     * 目前使用的 { CommonResult#getCode()} 属性
     */
    @ApiModelProperty(value = "结果码")
    @JsonProperty("result_code")
    @TableField("result_code")
    private Integer resultCode;

    /**
     * 结果提示
     * <p>
     * 目前使用的 { CommonResult#getMsg()} 属性
     */
    @ApiModelProperty(value = "结果提示")
    @JsonProperty("result_msg")
    @TableField("result_msg")
    private String resultMsg;

    /**
     * 结果数据
     * <p>
     * 如果是对象，则使用 JSON 格式化
     */
    @ApiModelProperty(value = "结果数据")
    @JsonProperty("result_data")
    @TableField("result_data")
    private String resultData;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @JsonProperty("create_time")
    @TableField("create_time")
    private LocalDateTime createTime;

    /**
     * 最后更新时间
     */
    @ApiModelProperty(value = "最后更新时间")
    @JsonProperty("update_time")
    @TableField("update_time")
    private LocalDateTime updateTime;

    /**
     * 创建者，目前使用 SysUser 的 id 编号
     * <p>
     * 使用 String 类型的原因是，未来可能会存在非数值的情况，留好拓展性。
     */
    @ApiModelProperty(value = "创建者")
    @JsonProperty("creator")
    @TableField("creator")
    private String creator;

    /**
     * 更新者，目前使用 SysUser 的 id 编号
     * <p>
     * 使用 String 类型的原因是，未来可能会存在非数值的情况，留好拓展性。
     */
    @ApiModelProperty(value = "更新者")
    @JsonProperty("updater")
    @TableField("updater")
    private String updater;

    /**
     * 是否删除
     */
    @ApiModelProperty(value = "是否删除")
    @JsonProperty("deleted")
    @TableField("deleted")
    private Boolean deleted;

    /**
     * 租户编号
     */
    @ApiModelProperty(value = "租户编号")
    @JsonProperty("tenant_id")
    @TableField("tenant_id")
    private String tenantId;

}
